#include "db_access.h"


namespace will {

	DbAccess::DbAccess(const std::string& db_host,
			const std::string& username,
			const std::string& password,
			const std::string& db,
			const int& db_port){

			//allocate and initialize a mysql object for connection
		if(mysql_init(&_m_handler) == NULL){
			throw std::runtime_error("mysql initialize failed ! cause:not enough memory...");
		}

		//connect to database
		if(NULL == mysql_real_connect(&_m_handler,db_host.c_str(),
					username.c_str(), password.c_str(),db.c_str(),db_port,NULL,0)){
						std::string error ("failed to connect to database.\n error:"); 
				error += mysql_error(&_m_handler);
			throw std::runtime_error(error);
		}

		//set client character set
		if(0 != mysql_query(&_m_handler,"set names gbk")){
			throw std::runtime_error("set character set error!");
		} 
	}

	DbAccess::~DbAccess(){
		mysql_close(&_m_handler);
		mysql_library_end();
	}
	int DbAccess::execute_query(const char* sql){
		//query failed!
		if (mysql_query(&_m_handler,sql) != 0)
			throw std::runtime_error(mysql_error(&_m_handler));
	//	query doesnot return data
	//	if (mysql_field_count(&_m_handler) == 0
	//query does not return data, it was not a select !
		return 0;

	}

	//query succeeded,process any data returned by it
	MYSQL_RES* DbAccess::get_result_set(){
		return mysql_use_result(&_m_handler);
	}

	int DbAccess::clear_query(MYSQL_RES* res){
		mysql_free_result(res);
		return 0;
	}


	ResultSetIterator::ResultSetIterator(MYSQL_RES* res){
		if(!res){
			//error handling
			throw std::runtime_error("empty result set");
		}
		else {
			_m_res = res;
			_m_record = mysql_fetch_row(_m_res);
		}
	}

	ResultSetIterator& ResultSetIterator::operator=(const ResultSetIterator& rhs){
		if(!_m_res){
			mysql_free_result(_m_res);
		}
		_m_res = rhs._m_res;
		_m_record = mysql_fetch_row(_m_res);
		return *this;
	}

	ResultSetIterator& ResultSetIterator::operator++(){
		_m_record = mysql_fetch_row(_m_res);
		return *this;
	}
	void  ResultSetIterator::operator++(int){
		++*this;
	}

	bool ResultSetIterator::operator==(const ResultSetIterator& rhs) const {
		if(this == &rhs) return true;
		if(this->_m_record == NULL && rhs._m_record == NULL)
			return true;
		else if(this->_m_record == NULL || rhs._m_record == NULL)
			return false;
		else return this->_m_record == rhs._m_record;
	}

	bool ResultSetIterator::operator!=(const ResultSetIterator& rhs) const{
		return !(*this == rhs);
	}



}

